﻿using Microsoft.DirectX.AudioVideoPlayback;
using Sanford.Multimedia.Midi;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;

namespace EasyPiano
{
    public class Util
    {
        private static int outDeviceID = 0;
        private static OutputDevice outDevice;

        public static void StartPlay(int nodeId)
        {
            nodeId = nodeId + 20;
            int volume = (int)(127 * GlobalData.volume / 100.0);
            outDevice.Send(new ChannelMessage(ChannelCommand.NoteOn, 0, nodeId, volume));
        }
        public static void StopPlay(int nodeId)
        {
            nodeId = nodeId + 20;
            outDevice.Send(new ChannelMessage(ChannelCommand.NoteOff, 0, nodeId, 0));
        }
        public static void StopAllPlay()
        {
            outDevice.Reset();
        }
        public static void CreateOutoutDevice()
        {
            outDevice = new OutputDevice(outDeviceID);
        }
        public static void DeleteOutputDevice()
        {
            outDevice.Close();
            outDevice.Dispose();
        }

        public static void AsynPlaySound(string path)
        {
            Thread thread = new Thread(PlaySound);
            thread.Start("Sound\\" + path);
        }

        static void PlaySound(object path)
        {
            Audio audio = new Audio((string)(path));
            audio.Volume = GlobalData.volume * 100 - 10000;
            audio.Play();
            while (audio.CurrentPosition < audio.Duration)
            {
                Thread.Sleep(250);
            }
            audio.Dispose();
        }

        public static void SaveMusicScore(string path, List<MusicScore> musicScores)
        {
            //创建XML文档对象
            XmlDocument doc = new XmlDocument();
            //创建第一行描述信息，并且添加到doc文档中
            XmlDeclaration dec = doc.CreateXmlDeclaration("1.0", "utf-8", null);
            doc.AppendChild(dec);
            //创建根节点
            XmlElement music = doc.CreateElement("Music");
            //将根节点添加到文档中
            doc.AppendChild(music);

            foreach (var data in musicScores)
            {
                //给根节点Books创建第一个子节点
                XmlElement score = doc.CreateElement("Score");

                score.SetAttribute("String", data.ScoreString);
                score.SetAttribute("DelayTime", data.duration.ToString());
                //将book1添加到根节点
                music.AppendChild(score);
            }

            doc.Save(path);
        }

        public static List<MusicScore> ReadMusicScore(string path)
        {
            List<MusicScore> result = new List<MusicScore>();
            XmlDocument doc = new XmlDocument();
            //加载要读取的XML
            doc.Load(path);
            //获得根节点
            XmlElement layout = doc.DocumentElement;
            //获得子节点 返回节点的集合
            XmlNodeList musicScores = layout.ChildNodes;
            foreach (XmlNode data in musicScores)
            {
                string str = data.Attributes["String"].Value;
                float duration = float.Parse(data.Attributes["DelayTime"].Value);
                result.Add(new MusicScore(SoundStringToIndex(str), duration));
            }
            return result;
        }

        public static int SoundStringToIndex(string str)
        {
            if (str == "0")
                return 0;
            int result = -1;
            try
            {
                int _base = 40;
                int[] _seven = { 0, 2, 4, 5, 7, 9, 11 };
                string txt = str;

                for (int i = 0; i < txt.Length; i++)
                {
                    if (txt[i] == '+')
                    {
                        _base += 12;
                    }
                    else if (txt[i] == '-')
                    {
                        _base -= 12;
                    }
                    else if (txt[i] >= '1' && txt[i] <= '7')
                    {
                        int sound = int.Parse(txt[i].ToString());
                        _base += _seven[sound - 1];
                    }
                    else if (txt[i] == '#')
                    {
                        _base++;
                    }
                }

                result = _base;
            }
            catch
            {

            }
            return result;
        }
        public static string SoundIndexToString(int soundIndex)
        {
            if (soundIndex == 0)
                return "0";
            if (soundIndex < 0 || soundIndex > 88)
                return "";
            string result = "";
            int _base = 40;
            int[] _seven = { 0, 2, 4, 5, 7, 9, 11 };
            int[] _seven1 = { -12, -10, -8, -7, -5, -3, -1 };
            int x = soundIndex - _base;
            if (x >= 0)
            {
                int rank = x / 12;
                int r = x % 12;
                for (int i = 0; i < rank; i++)
                {
                    result += "+";
                }
                for (int i = 0; i < 6; i++)
                {
                    if (r >= _seven[i] && r < _seven[i + 1])
                    {
                        result += (i + 1);
                        if (r > _seven[i])
                        {
                            result += "#";
                        }
                        break;
                    }
                }
                if (r == _seven[6])
                {
                    result += 7;
                }
            }
            else
            {
                int rank = (x + 1) / -12;
                int r = x % -12;
                for (int i = 0; i <= rank; i++)
                {
                    result += "-";
                }
                for (int i = 0; i < 6; i++)
                {
                    if (r == 0)
                    {
                        result += 1;
                        break;
                    }
                    if (r >= _seven1[i] && r < _seven1[i + 1])
                    {
                        result += (i + 1);
                        if (r > _seven1[i])
                        {
                            result += "#";
                        }
                        break;
                    }
                }
                if (r == _seven1[6])
                {
                    result += 7;
                }
            }
            return result;
        }

        public static int GetSoundStringRank(string str)
        {
            int rank = 0;
            for(int i=0;i<str.Length;i++)
            {
                if (str[i] == '+')
                    rank++;
                else if (str[i] == '-')
                    rank--;
            }
            return rank;
        }
        public static string GetSoundStringNumber(string str)
        {
            string result = "";
            for (int i = 0; i < str.Length; i++)
            {
                if (str[i] >= '0' && str[i] <= '7')
                    result += str[i];
                else if (str[i] == '#')
                    result += str[i];
            }
            return result;
        }

        public static List<KeyMusic> ReadLayout(string path)
        {            
            List<KeyMusic> result = new List<KeyMusic>();
            XmlDocument doc = new XmlDocument();
            //加载要读取的XML
            doc.Load(path);
            //获得根节点
            XmlElement layout = doc.DocumentElement;
            //获得子节点 返回节点的集合
            XmlNodeList keyMusics = layout.ChildNodes;
            foreach (XmlNode data in keyMusics)
            {
                XmlNode key = data.ChildNodes[0];
                XmlNode fileName = data.ChildNodes[1];
                result.Add(new KeyMusic((System.Windows.Forms.Keys)Enum.Parse(typeof(System.Windows.Forms.Keys), key.InnerText), int.Parse(fileName.InnerText)));
            }
            return result;
        }

        public static void SaveLayout(string path, List<KeyMusic> keyMusics)
        {
            //创建XML文档对象
            XmlDocument doc = new XmlDocument();
            //创建第一行描述信息，并且添加到doc文档中
            XmlDeclaration dec = doc.CreateXmlDeclaration("1.0", "utf-8", null);
            doc.AppendChild(dec);
            //创建根节点
            XmlElement layout = doc.CreateElement("Layout");
            //将根节点添加到文档中
            doc.AppendChild(layout);

            foreach (var data in keyMusics)
            {
                //给根节点Books创建第一个子节点
                XmlElement keyMusic = doc.CreateElement("KeyMusic");
                //将book1添加到根节点
                layout.AppendChild(keyMusic);

                //给book1添加三个子节点
                XmlElement key = doc.CreateElement("Key");
                key.InnerText = data.key.ToString();
                keyMusic.AppendChild(key);

                XmlElement fileName = doc.CreateElement("Index");
                fileName.InnerText = data.index.ToString();
                keyMusic.AppendChild(fileName);
            }

            doc.Save(path);
        }
    }
}
